package com.zh.work.service.platform.agent.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zh.common.entity.Oauth;
import com.zh.work.dao.platform.agent.AgentInfoMapper;
import com.zh.work.dao.platform.agent.QrCodeAgentFeeMapper;
import com.zh.work.dao.platform.branch.BranchAppMapper;
import com.zh.work.dao.platform.merch.MerchInfoMapper;
import com.zh.work.entity.AgentRecordEntity;
import com.zh.work.entity.agent.AgentInfoEntity;
import com.zh.work.entity.agent.QrCodeAgentFee;
import com.zh.work.entity.branch.BranchAppEntity;
import com.zh.work.entity.branch.BranchInfoEntity;
import com.zh.work.entity.merch.MerchInfoEntity;
import com.zh.work.entity.merch.QrCodeMerchFee;
import com.zh.work.service.platform.agent.AgentInfoService;
import com.zh.work.util.plateform.ServiceUtil;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.task.TaskExecutor;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.SQLException;
import java.util.*;

/**
 * code is far away from bug with the animal protecting
 * ┏┓　　　┏┓
 * ┏┛┻━━━┛┻┓
 * ┃　　　　　　　┃
 * ┃　　　━　　　┃
 * ┃　┳┛　┗┳　┃
 * ┃　　　　　　　┃
 * ┃　　　┻　　　┃
 * ┃　　　　　　　┃
 * ┗━┓　　　┏━┛
 * 　　┃　　　┃神兽保佑
 * 　　┃　　　┃代码无BUG！
 * 　　┃　　　┗━━━┓
 * 　　┃　　　　　　　┣┓
 * 　　┃　　　　　　　┏┛
 * 　　┗┓┓┏━┳┓┏┛
 * 　　　┃┫┫　┃┫┫
 * 　　　┗┻┛　┗┻┛
 *
 * @Description: AgentInfo设置业务逻辑实现层
 * @Author: Li.HuiNeng
 * @Create in: 2019/08/28
 * @Version: 1.0.1
 */
@Service
public class AgentInfoServiceImpl extends ServiceImpl<AgentInfoMapper, AgentInfoEntity> implements AgentInfoService {

    private static final Logger log = LoggerFactory.getLogger(AgentInfoServiceImpl.class);


    @Autowired
    private AgentInfoMapper agentInfoMapper;

    @Autowired
    private MerchInfoMapper merchInfoMapper;

    @Autowired
    private BranchAppMapper branchAppMapper;

    @Qualifier("taskExecutor")
    @Autowired
    private TaskExecutor taskExecutor;

    @Override
    public IPage<AgentInfoEntity> selectAgentPage(Page<AgentInfoEntity> page, AgentInfoEntity agentInfoEntity) {
        return this.agentInfoMapper.selectPage(
                page,
                new LambdaQueryWrapper<AgentInfoEntity>()
                        .between(ObjectUtils.allNotNull(agentInfoEntity.getStartDateTime(),agentInfoEntity.getEndDateTime()), AgentInfoEntity::getOpenTime,
                                agentInfoEntity.getStartDateTime(), agentInfoEntity.getEndDateTime())
                        .between((ObjectUtils.allNotNull(agentInfoEntity.getAddStartTime(),agentInfoEntity.getAddEndTime())), AgentInfoEntity::getAddTime,
                                agentInfoEntity.getAddStartTime(), agentInfoEntity.getAddEndTime())
                        .eq(Objects.nonNull(agentInfoEntity.getStatus()), AgentInfoEntity::getStatus, agentInfoEntity.getStatus())
                        .eq(Objects.nonNull(agentInfoEntity.getAuditStatus()), AgentInfoEntity::getAuditStatus, agentInfoEntity.getAuditStatus())
                        .eq(StringUtils.isNotEmpty(agentInfoEntity.getBranchNo()), AgentInfoEntity::getBranchNo, agentInfoEntity.getBranchNo())
                        .like(StringUtils.isNotEmpty(agentInfoEntity.getAgentNo()), AgentInfoEntity::getAgentNo, agentInfoEntity.getAgentNo())
                        .like(StringUtils.isNotEmpty(agentInfoEntity.getLinkMan()), AgentInfoEntity::getLinkMan, agentInfoEntity.getLinkMan())
                        .like(StringUtils.isNotEmpty(agentInfoEntity.getSuperAgent()), AgentInfoEntity::getSuperAgent, agentInfoEntity.getSuperAgent())
                        .like(StringUtils.isNotEmpty(agentInfoEntity.getMobile()), AgentInfoEntity::getMobile, agentInfoEntity.getMobile())
                        .like(StringUtils.isNotEmpty(agentInfoEntity.getAccountNo()), AgentInfoEntity::getAccountNo, agentInfoEntity.getAccountNo())
                        .inSql(StringUtils.isNotEmpty(agentInfoEntity.getSuperAgent()), AgentInfoEntity::getAgentNo, "select agentno from agent_relate where super_agentno =" + agentInfoEntity.getSuperAgent())
        );
    }


    /**
     * 根据账号判断当前账号是属于什么类型与级别
     * <p>
     * 机构账户：
     * 1. 添加一级代理商 ----> 按照机构资料添加费率信息,且费率信息不得高于机构账户所属机构中的费率
     * 2. 直接添加二级或三级代理商时，需要获取上级代理商信息，并且费率不得高于上级代理商
     * <p>
     * 代理商账户：
     * 1. 一级代理商添加新的代理商时只能为二级代理商, 费率信息需要比对当前费率且不的高于当前账户所属代理商费率
     * 2. 二级代理商添加下级代理商，需要先获取当前账户代理商信息然后在做对比，符合条件添加
     * 3. 三级代理如上
     * <p>
     * ### 注： 新增时需要新增关联表
     */
    @Transactional
    @Override
    public int putAgentInfo(AgentInfoEntity agentInfoEntity) throws Exception {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        Oauth auth = (Oauth) authentication.getPrincipal();
        MerchInfoEntity merchInfoEntity = new MerchInfoEntity();
        /** 获取地区编码 */
        List<String> list = JSON.parseArray(agentInfoEntity.getProvinceCity(), String.class);
        String areaCode = list.get(list.size() - 1);
        agentInfoEntity.setAreaCode(areaCode);
        /** 构造代理商编号 */
        String agentNo = areaCode + ServiceUtil.getAgentMaxId(areaCode);
        /** 添加代理商编号 */
        agentInfoEntity.setAgentNo(agentNo);
        ServiceUtil.setImageInfo(agentInfoEntity, null);
        /*
         * @Author: Li.HuiNeng
         * @Date: 2019/11/19
         * @Description: 添加一级代理商，由于资料缺失，机构表中费率信息与代理商表中费率信息不一致，
         * 故采用，原代码中记录的默认值
         */
        /** 解构二维码费率JSON字符串 */
        List<QrCodeAgentFee> feeList = JSON.parseArray(agentInfoEntity.getQrCodeRateJson(), QrCodeAgentFee.class);
        if (feeList == null)  return -14;
//        if (auth.getUserType() == 2 || auth.getUserType() == 1) {
            List<QrCodeAgentFee> agentFeesList = new ArrayList<>();
            int count = 0;
            if (agentInfoEntity.getAgentLevel() == 1) {
                /** 获取机构费率信息 */
                BranchInfoEntity branchInfoEntity = agentInfoMapper.getBranchOtherFee(agentInfoEntity.getBranchNo());
                /** 获取机构费率 */
                List<QrCodeAgentFee> branchFees = agentInfoMapper.getBranchFee(agentInfoEntity.getBranchNo());
                /** 验证二维码费率 */
                count = ServiceUtil.qrCodeFeeValid(feeList, branchFees);
                if (count <= 0) return -12;
                /** 验证 网关, 快捷，Mpos等费率 */
                int i = ServiceUtil.branchFeeValid(agentInfoEntity, null, branchInfoEntity);
                if (i < 0) return i;
            }
            else {
                /** 获取上级代理商二维码费率 */
                agentFeesList = this.agentInfoMapper.getAgentQrCodeFee(agentInfoEntity.getSuperAgent());
                /** 验证当前与上级的二维码费率信息 */
                count = ServiceUtil.qrCodeFeeValid(feeList, agentFeesList);
                if (count <= 0) return -12;
                /** 获取选中代理代理费率信息 */
                AgentInfoEntity agentInfoParent = agentInfoMapper.selectOne(new LambdaQueryWrapper<AgentInfoEntity>()
                .eq(AgentInfoEntity::getAgentNo, agentInfoEntity.getSuperAgent()));
                int i = ServiceUtil.branchFeeValid(agentInfoEntity, agentInfoParent, null);
                if (i < 0) return i;
            }
            // 验证全部通过,新增代理商费率信息
            try {
                feeList.forEach(f -> {
                    f.setAgentNo(agentNo);
                    f.setBranchNo(agentInfoEntity.getBranchNo());
                    f.insert();
                });
                final List<QrCodeAgentFee> feeList1 = feeList;
                taskExecutor.execute(new Runnable() {
                    @Override
                    public void run() {
                        new AgentRecordEntity(null, JSON.toJSONString(feeList1), auth.getId(), "f.insert()").insert();
                    }
                });
            } catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException("二维码费率信息添加错误");
            }
        /** 新增代理商 */
        try {
            int k = this.agentInfoMapper.insert(agentInfoEntity);
            if (k > 0) {
                try {
                    agentInfoMapper.putAgentForKeyByUser(auth.getId(), agentInfoEntity.getId());
                    taskExecutor.execute(new Runnable() {
                        @Override
                        public void run() {
                            new AgentRecordEntity(null, auth.getId().toString() + "#" + agentInfoEntity.getId(),
                                    auth.getId(), "putAgentForKeyByUser()").insert();
                        }
                    });
                } catch (NumberFormatException e) {
                    throw new SQLException("新增代理商时插入外键表失败");
                }
            } else return -1;
        } catch (Exception e) {
            e.printStackTrace();
            throw new SQLException("执行添加代理商出错");
        }
        /**
         * **************************************************
         * 商户信息添加
         * 暂时只有添加一级代理时添加商户信息
         * **************************************************
         */
        if (agentInfoEntity.getAgentLevel() == 1) {
            try {
                merchInfoEntity = this.merchInfoMapper.selectOne(new LambdaQueryWrapper<MerchInfoEntity>()
                        .eq(MerchInfoEntity::getMobile, agentInfoEntity.getMobile())
                        .eq(MerchInfoEntity::getBranchNo, agentInfoEntity.getBranchNo())
                );
                // 不存在则创建.存在则修改
                if (merchInfoEntity == null) {
                    // 机构开通了app功能,并且app开通分销商功能,直接根据代理信息创建商户信息
                    BranchAppEntity branchAppEntity = this.branchAppMapper.selectOne(new LambdaQueryWrapper<BranchAppEntity>()
                            .eq(BranchAppEntity::getBranchNo, agentInfoEntity.getBranchNo())
                    );
                    if (branchAppEntity != null && branchAppEntity.getOpenSale() == 1) {
                        // 设置商户属性
                        merchInfoEntity = ServiceUtil.creatMerchBean(agentInfoEntity, branchAppEntity, merchInfoEntity.getMcc());
                        // 新增商户信息
                        if (merchInfoEntity.insert()) {
                            // 商户新增成功，插入商户二维码费率信息,将当前添加商户费率信息赋予商户
                            String merchNo = merchInfoEntity.getMerchNo();
                            if (feeList.size() > 0) {
                                for (int j = 0; j < feeList.size(); j++) {
                                    //xxx 此处无法将代理商费率直接转为商户费率
                                    QrCodeMerchFee m = new QrCodeMerchFee();
                                    QrCodeAgentFee af = feeList.get(j);
                                    m.setPayType(af.getPayType());
                                    m.setRate(af.getRate());
                                    m.setScanType(af.getScanType());
                                    m.setSettleType(af.getSettleType());
                                    // 设置机构编号
                                    m.setBranchNo(agentInfoEntity.getBranchNo());
                                    // 设置代理商编号
                                    m.setAgentNo(agentInfoEntity.getAgentNo());
                                    // 设置商户编号
                                    m.setMerchNo(merchNo);
                                    if (m.insert()) {
                                        taskExecutor.execute(new Runnable() {
                                            @Override
                                            public void run() {
                                                // 记录历史记录
                                                new AgentRecordEntity(null, JSON.toJSONString(agentInfoEntity) + JSON.toJSONString(m),
                                                        auth.getId(), "putAgentInfo()").insert();
                                            }
                                        });
                                    }
                                }
                            }
                        }
                    }
                } else {
                    log.info("手机号为{}代理商下以存在{}商户,将存在商户上级代理商修改为{}代理商", agentInfoEntity.getMobile(), merchInfoEntity.getMerchNo(), agentInfoEntity.getAgentNo());
                    MerchInfoEntity beforeMerch = merchInfoEntity;
                    if (this.merchInfoMapper.updateMerchParentNo(agentInfoEntity.getAgentNo(), String.valueOf(agentInfoEntity.getId())) > 0) {
                        log.info("编号为{}的商户修改成为编号{}代理商的下级商户!", beforeMerch.getMerchNo(), beforeMerch.getSuperAgent());
                        new AgentRecordEntity(JSON.toJSONString(beforeMerch), JSON.toJSONString(merchInfoEntity), auth.getId(), "updateById()").insert();
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException("添加商户信息出错!");
            }
        }
        return 1;
    }

    @Autowired
    private QrCodeAgentFeeMapper qrCodeAgentFeeMapper;

    @Transactional
    @Override
    public int modAgentInfo(AgentInfoEntity agentInfoEntity) throws Exception {
        int i = 0;
        // 获取提交的二维码费率信息
        List<QrCodeAgentFee> qrCodeAgentFees = JSON.parseArray(agentInfoEntity.getQrCodeRateJson(), QrCodeAgentFee.class);
        if (qrCodeAgentFees == null) return -1;
        else  {
            try {
                // 查询数据库中是否存在代理商二维码信息
                Map<String,Long> map = agentInfoMapper.getMerchantFee(agentInfoEntity.getAgentNo());
                if (map.get("num") != 0) {
                // 删除指定代理商二维码费率信息
                    this.qrCodeAgentFeeMapper.delete(new LambdaQueryWrapper<QrCodeAgentFee>().eq(QrCodeAgentFee::getAgentNo, agentInfoEntity.getAgentNo()));
                }
                // 新增
                qrCodeAgentFees.forEach( f -> {
                    f.setAgentNo(agentInfoEntity.getAgentNo());
                    f.setBranchNo(agentInfoEntity.getBranchNo());
                    this.qrCodeAgentFeeMapper.insert(f);
                });
            } catch (Exception e) {
                e.printStackTrace();
                return -2;
            }
        }
        // 一级代理
        if (agentInfoEntity.getAgentLevel() == 1) {
            // 对比二维码费率
            List<QrCodeAgentFee> qrCodeAgentFees2 = agentInfoMapper.getBranchFee(agentInfoEntity.getBranchNo());
            i = ServiceUtil.qrCodeFeeValid(qrCodeAgentFees,qrCodeAgentFees2);
            if (i < 0) return i;
            // 对比其他费率
            BranchInfoEntity branchInfoEntity = agentInfoMapper.getBranchOtherFee(agentInfoEntity.getBranchNo());
            i = ServiceUtil.branchFeeValid(agentInfoEntity, null, branchInfoEntity);
            if (i < 0) return i;
        } else {
            // 对比二维码费率
            List<QrCodeAgentFee> qrCodeAgentFees2 = agentInfoMapper.getAgentQrCodeFee(agentInfoEntity.getSuperAgent());
            i = ServiceUtil.qrCodeFeeValid(qrCodeAgentFees,qrCodeAgentFees2);
            if (i < 0) return  i;
            // 对比其他费率
            AgentInfoEntity agentInfoEntity1 = agentInfoMapper.selectOne(new LambdaQueryWrapper<AgentInfoEntity>()
                    .eq(AgentInfoEntity::getAgentNo, agentInfoEntity.getSuperAgent()));
            i = ServiceUtil.branchFeeValid(agentInfoEntity, agentInfoEntity1, null);
            if (i < 0) return i;
        }
        // 重新设置上传的图片
        ServiceUtil.setImageInfo(agentInfoEntity, null);
        // 验证全部通过,修改信息
        i = agentInfoMapper.updateById(agentInfoEntity);
        if (i < 0) return -13;
        return 1;
    }

    @Override
    public int checkAgentByName(String name) {
        return this.agentInfoMapper.selectCount(new LambdaQueryWrapper<AgentInfoEntity>()
                .eq(AgentInfoEntity::getAgentName, name)
                .or()
                .eq(AgentInfoEntity::getFullName, name));
    }

    @Override
    public int delAgentAndUser(Long agentId) {
        return this.agentInfoMapper.delAgentAndUser(agentId);
    }

    @Override
    public int modAgentStatus(String agentId, String remark, String status) {
        return this.agentInfoMapper.modAgentStatus(agentId, remark, status);
    }

    @Override
    public List<QrCodeAgentFee> getAgentQrCodeRate(String agentNo) {
        return agentInfoMapper.getAgentQrCodeFee(agentNo);
    }

    @Override
    public List<AgentInfoEntity> getAgentList() {
        return agentInfoMapper.selectList(new LambdaQueryWrapper<AgentInfoEntity>()
                .select(AgentInfoEntity::getId,AgentInfoEntity::getAgentNo, AgentInfoEntity::getAgentName));
    }

    @Override
    public List<AgentInfoEntity> getAgentListByLevel(Integer agentLevel, Integer id) {
        return agentInfoMapper.selectList(new LambdaQueryWrapper<AgentInfoEntity>()
                .select(AgentInfoEntity::getId, AgentInfoEntity::getAgentNo, AgentInfoEntity::getAgentName)
                .eq(AgentInfoEntity::getAgentLevel, agentLevel));
    }


    @Override
    public List<AgentInfoEntity> getAgentListByBranchNo(String branchNo) {
        return agentInfoMapper.selectList(new LambdaQueryWrapper<AgentInfoEntity>()
        .select(AgentInfoEntity::getAgentNo,AgentInfoEntity::getAgentName)
        .eq(AgentInfoEntity::getBranchNo, branchNo));
    }
}
